package com.healthcarex.hip.saas.security.service.impl;

import com.healthcarex.hip.saas.common.model.BaseModel;
import com.healthcarex.hip.saas.security.dao.ResourceDao;
import com.healthcarex.hip.saas.security.dao.RoleDao;
import com.healthcarex.hip.saas.security.dao.RoleResourceDao;
import com.healthcarex.hip.saas.security.model.RoleWithResource;
import com.healthcarex.hip.saas.security.model.SysResource;
import com.healthcarex.hip.saas.security.model.SysRole;
import com.healthcarex.hip.saas.security.model.SysRoleResource;
import com.healthcarex.hip.saas.security.service.IRoleResourceService;
import com.healthcarex.hip.saas.security.service.IRoleService;
import com.healthcarex.hip.saas.security.service.IUserRoleService;
import com.healthcarex.hip.saas.security.util.SecurityUtils;
import com.healthcarex.hip.saas.mybatis.service.impl.BaseServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author chenpan
 * @ClassName: RoleServiceImpl
 * description:
 * @date 2018-04-02 17:21
 */
@Service
public class RoleServiceImpl extends BaseServiceImpl<SysRole> implements IRoleService {

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private ResourceDao resourceDao;

    @Autowired
    private RoleResourceDao roleResourceDao;

    @Autowired
    private IUserRoleService userRoleService;

    @Autowired
    private IRoleResourceService roleResourceService;

    @Override
    public List<SysRole> findUserRole(String userName) {
        return this.roleDao.findUserRole(userName);
    }

    @Override
    public List<SysRole> findAllRole(SysRole role) {
        Example example = new Example(SysRole.class);
        if ((StringUtils.isNotBlank(role.getRoleName()))) {
            example.createCriteria().andCondition("role_name=", role.getRoleName());
        }
        if ((StringUtils.isNotBlank(role.getRoleCode()))) {
            example.createCriteria().andCondition("role_code=", role.getRoleCode());
        }
        example.setOrderByClause("create_time");
        return this.selectByExample(example);
    }

    @Override
    public List<RoleWithResource> findRoleWithResources(SysRole role) {

        List<RoleWithResource> roles = roleDao.findRoles(role);
        if (roles != null && !roles.isEmpty()) {
            for (RoleWithResource r : roles) {
                List<SysResource> resourceTreeList = resourceDao.findRoleResource(r.getId());
                r.setResources(resourceTreeList);
            }
        }

        return roles;
    }

    @Override
    public RoleWithResource findRoleWithResources(Integer roleId) {
        RoleWithResource roleWithResource = this.roleDao.findById(roleId);

        return roleWithResource;
    }

    @Override
    public SysRole findByCode(String roleCode) {
        Example example = new Example(SysRole.class);
        example.createCriteria().andCondition("lower(role_code)=", roleCode.toLowerCase());
        List<SysRole> list = this.roleDao.selectByExample(example);
        if (list.size() == 0) {
            return null;
        } else {
            return list.get(0);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    @CacheEvict(value = {"authority", "resource:tree", "permission", "urlPermission"}, allEntries = true)
    public void addRole(SysRole role, Integer[] resourceIds) {
        // 保存角色
        role.setId(this.getSequence(BaseModel.BASE_SEQ));
        role.setCreateTime(new Date());
        role.setCreateBy(SecurityUtils.getUsername());
        this.save(role);
        //保存角色资源
        if (resourceIds != null) {
            for (Integer resourceId : resourceIds) {
                SysRoleResource rr = new SysRoleResource();
                rr.setResourceId(resourceId);
                rr.setRoleId(role.getId());
                this.roleResourceDao.insertSelective(rr);
            }
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    @CacheEvict(value = {"authority", "resource:tree", "permission","urlPermission"}, allEntries = true)
    public void updateRole(SysRole role, Integer[] resourceIds) {
        //更新角色
        role.setUpdateBy(SecurityUtils.getUsername());
        role.setUpdateTime(new Date());
        this.roleDao.updateByPrimaryKeySelective(role);
        Example example = new Example(SysRoleResource.class);
        example.createCriteria().andCondition("role_id=", role.getId());
        //删除角色资源
        this.roleResourceDao.deleteByExample(example);
        // 插入角色资源
        if (resourceIds != null) {
            for (Integer resourceId : resourceIds) {
                SysRoleResource rr = new SysRoleResource();
                rr.setResourceId(resourceId);
                rr.setRoleId(role.getId());
                this.roleResourceDao.insertSelective(rr);
            }
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    @CacheEvict(value = {"authority", "resource:tree", "permission","urlPermission"}, allEntries = true)
    public void deleteRoles(String roleIds) {
        List<String> list = Arrays.asList(roleIds.split(","));
        this.batchDelete(list, "id", SysRole.class);

        this.roleResourceService.deleteRoleResourcesByRoleId(roleIds);
        this.userRoleService.deleteUserRolesByRoleId(roleIds);
    }
}
